/*
 * @Author: jingfuu@163.com
 * @Date: 2024-11-26 10:19:38
 * @LastEditTime: 2024-12-11 13:48:11
 * @Description: file content
 */
import {
  Body,
  Controller,
  Delete,
  Get,
  Logger,
  Param,
  Post,
  Put,
  Query,
  Res,
} from '@nestjs/common';
import { ApiOperation, ApiTags } from '@nestjs/swagger';
import DictService from '../service/DictService';
import DictQueryParam from '../param/DictQueryParam';
import DictTypeDto from '../dto/DictTypeDto';
import { R } from 'src/common/R';
import PageResult from 'src/common/PageResult';
import { Response } from 'express';
import ServiceException from 'src/common/ServiceException';
import DictDataDto from '../dto/DictDataDto';
import { PreAuthorize } from 'src/common/decorator/PreAuthorizeDecorator';
import { Log } from 'src/common/decorator/LogDecorator';
import BusinessType from 'src/common/enum/BusinessType';

/*
 * @Author: jingfuu@163.com
 * @Date: 2024-11-26 10:19:38
 * @LastEditTime: 2024-11-26 11:24:52
 * @Description: 字典接口
 */
@ApiTags('字典接口')
@Controller('system/dict')
class DictController {
  private readonly logger = new Logger(DictController.name);
  constructor(private dictService: DictService) {}

  @PreAuthorize('system:dict:list')
  @ApiOperation({ summary: '分页查询字典类型' })
  @Get('/type/list')
  async findDictTypeList(
    @Query() param: DictQueryParam,
  ): Promise<R<DictTypeDto>> {
    this.logger.log(
      'query dict type list start, param:' + JSON.stringify(param),
    );
    const result: PageResult<DictTypeDto> = await this.dictService.list(param);
    return R.page(result);
  }

  @ApiOperation({ summary: '字典类型列表' })
  @Get('/type/optionselect')
  async dictTypeOptionselect(): Promise<R<DictTypeDto[]>> {
    this.logger.log('query dict type optionselect start');
    const result: DictTypeDto[] = await this.dictService.findDictTypeList();
    return R.ok(result);
  }

  @Log({ title: '字典类型管理', businessType: BusinessType.DELETE })
  @PreAuthorize('system:dict:remove')
  @ApiOperation({ summary: '删除字典类型' })
  @Delete('/type/:id')
  async deleteDictType(@Param('id') id: string): Promise<R<any>> {
    if (id.indexOf(',') > -1) {
      for (const item of id.split(',')) {
        await this.dictService.deleteDictType(Number.parseInt(item));
      }
    } else {
      await this.dictService.deleteDictType(Number.parseInt(id));
    }
    return R.ok();
  }

  /**
   * 字典类型详情
   */
  @PreAuthorize('system:dict:query')
  @ApiOperation({ summary: '字典类型详情' })
  @Get('/type/:id(\\d+)')
  async findDictTypeDetail(@Param('id') id: number): Promise<R<DictTypeDto>> {
    return R.ok(await this.dictService.findDictTypeDetail(id));
  }

  /**
   * 字典类型修改
   */
  @Log({ title: '字典类型管理', businessType: BusinessType.UPDATE })
  @PreAuthorize('system:dict:edit')
  @ApiOperation({ summary: '字典类型修改' })
  @Put('/type')
  async modifyDictType(@Body() dict: DictTypeDto) {
    await this.dictService.updateDictType(dict);
    return R.ok();
  }

  /**
   * 字典类型新增
   */
  @Log({ title: '字典类型管理', businessType: BusinessType.INSERT })
  @PreAuthorize('system:dict:add')
  @ApiOperation({ summary: '字典类型新增' })
  @Post('/type')
  async createDictType(@Body() dict: DictTypeDto) {
    await this.dictService.createDictType(dict);
    return R.ok();
  }

  /**
   * 字典类型导出
   */
  @Log({ title: '字典类型管理', businessType: BusinessType.EXPORT })
  @PreAuthorize('system:dict:export')
  @ApiOperation({ summary: '字典类型导出' })
  @Post('/type/export')
  async exportDictType(@Body() param: DictQueryParam, @Res() res: Response) {
    try {
      const buffer = await this.dictService.exportDictType(param);
      res.set({
        'Content-Type': 'application/vnd.ms-excel',
        'Content-Disposition': 'attachment; filename=dictType.xlsx',
      });
      res.send(buffer);
    } catch (error) {
      this.logger.error('字典类型导出失败', error.stack);
      throw new ServiceException('字典类型导出失败');
    }
  }

  /**
   * 根据字段类型查询字典值
   */
  @Get('data/type/:dictType')
  async findDictDataByType(@Param('dictType') dictType: string) {
    return R.ok(await this.dictService.findDictDataByType(dictType));
  }

  /**
   * 刷新字典缓存
   */
  @Log({ title: '字典数据管理', businessType: BusinessType.OTHER })
  @ApiOperation({ summary: '刷新字典缓存' })
  @Post('type/refreshCache')
  async refreshCache() {
    await this.dictService.refreshCache();
    return R.ok();
  }

  /**
   * 字典数据列表查询
   */
  @PreAuthorize('system:dict:list')
  @ApiOperation({ summary: '字典数据列表查询' })
  @Get('data/list')
  async list(@Query() param: DictQueryParam): Promise<R<DictDataDto>> {
    return R.page(await this.dictService.listData(param));
  }

  @Log({ title: '字典数据管理', businessType: BusinessType.DELETE })
  @PreAuthorize('system:dict:remove')
  @ApiOperation({ summary: '删除字典数据' })
  @Delete('/data/:id(\\d+)')
  async deleteDictData(@Param('id') id: string): Promise<R<any>> {
    if (id.indexOf(',') > -1) {
      for (const item of id.split(',')) {
        await this.dictService.deleteDictData(Number.parseInt(item));
      }
    } else {
      await this.dictService.deleteDictData(Number.parseInt(id));
    }
    return R.ok();
  }

  /**
   * 查询字典数据详情
   */
  @PreAuthorize('system:dict:query')
  @ApiOperation({ summary: '查询字典数据详情' })
  @Get('/data/:id(\\d+)')
  async findDictDataDetail(@Param('id') id: number): Promise<R<DictDataDto>> {
    return R.ok(await this.dictService.findDictDataById(id));
  }

  /**
   * 新增字典数据
   */
  @Log({ title: '字典数据管理', businessType: BusinessType.INSERT })
  @PreAuthorize('system:dict:add')
  @ApiOperation({ summary: '新增字典数据' })
  @Post('/data')
  async createDictData(@Body() dict: DictDataDto): Promise<R<void>> {
    await this.dictService.createDictData(dict);
    return R.ok();
  }

  /**
   * 修改字典数据
   */
  @Log({ title: '字典数据管理', businessType: BusinessType.UPDATE })
  @PreAuthorize('system:dict:edit')
  @ApiOperation({ summary: '修改字典数据' })
  @Put('/data')
  async updateDictData(@Body() dict: DictDataDto): Promise<R<void>> {
    await this.dictService.updateDictData(dict);
    return R.ok();
  }

  /**
   * 字典类型导出
   */
  @Log({ title: '字典数据管理', businessType: BusinessType.EXPORT })
  @PreAuthorize('system:dict:export')
  @ApiOperation({ summary: '字典数据导出' })
  @Post('/data/export')
  async exportDictData(@Body() param: DictQueryParam, @Res() res: Response) {
    try {
      const buffer = await this.dictService.exportDictData(param);
      res.set({
        'Content-Type': 'application/vnd.ms-excel',
        'Content-Disposition': 'attachment; filename=dictData.xlsx',
      });
      res.send(buffer);
    } catch (error) {
      this.logger.error('字典数据导出失败', error.stack);
      throw new ServiceException('字典数据导出失败');
    }
  }
}
export default DictController;
